home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PCMania 44
/
PCMania CD44_1.iso
/
pcmania
/
treal44
/
3dtoshi
/
3d.cpp
next >
Wrap
C/C++ Source or Header
|
1995-12-03
|
66KB
|
2,214 lines
// 3d.cpp
//
// Copyright (c) 1995 by Toshiaki Tsuji, all rights reserved.
#include "stdgui.h"
#include "3d.h"
#include <math.h>
#include <search.h>
#define MIN_Z_DISTANCE 10
LONG NumShadeLevels=(LONG)1;
LONG MaxShadeNumber=(LONG)1<<8;
//*************************************************
//
// Matrix Operations
//
//*************************************************
VOID InitMatrix ( MATRIX Matrix )
{
INT i,j;
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
if (i==j)
Matrix[i][j] = 1;
else
Matrix[i][j] = 0;
} // End for
} // End for
} // End of InitMatrix
VOID CopyMatrix ( MATRIX Dest, MATRIX Src )
{
INT i,j;
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
Dest[i][j] = Src[i][j];
} // End for
} // End for
} // End of CopyMatrix
VOID MultMatrix ( MATRIX Dest, MATRIX Mat1, MATRIX Mat2 )
{
INT i,j,k;
for (i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
Dest[i][j] = 0;
for (k=0;k<4;k++)
{
Dest[i][j] += Mat1[i][k]*Mat2[k][j];
} // End for
} // End for
} // End for
} // End of MultMatrix
VOID Translate ( MATRIX Matrix, double x, double y, double z )
{
MATRIX TMat;
MATRIX Mat1;
TMat[0][0]= 1; TMat[0][1]= 0; TMat[0][2]= 0; TMat[0][3]= 0;
TMat[1][0]= 0; TMat[1][1]= 1; TMat[1][2]= 0; TMat[1][3]= 0;
TMat[2][0]= 0; TMat[2][1]= 0; TMat[2][2]= 1; TMat[2][3]= 0;
TMat[3][0]= x; TMat[3][1]= y; TMat[3][2]= z; TMat[3][3]= 1;
MultMatrix ( Mat1, Matrix, TMat );
CopyMatrix ( Matrix, Mat1 );
} // End of Translet for G3DENGINE
VOID Rotate ( MATRIX Matrix, double xa, double ya, double za )
{
MATRIX XMat,YMat,ZMat,Mat1,Mat2;
double Xa,Ya,Za;
double Sx,Cx,Sy,Cy,Sz,Cz;
// Change degree to radian
Xa = xa*6.281/360;
Ya = ya*6.281/360;
Za = za*6.281/360;
Sx = sin ( Xa );
Cx = cos ( Xa );
Sy = sin ( Ya );
Cy = cos ( Ya );
Sz = sin ( Za );
Cz = cos ( Za );
XMat[0][0]= 1; XMat[0][1]= 0; XMat[0][2]= 0; XMat[0][3]= 0;
XMat[1][0]= 0; XMat[1][1]= Cx; XMat[1][2]= Sx; XMat[1][3]= 0;
XMat[2][0]= 0; XMat[2][1]=-Sx; XMat[2][2]= Cx; XMat[2][3]= 0;
XMat[3][0]= 0; XMat[3][1]= 0; XMat[3][2]= 0; XMat[3][3]= 1;
YMat[0][0]= Cy; YMat[0][1]= 0; YMat[0][2]=-Sy; YMat[0][3]= 0;
YMat[1][0]= 0; YMat[1][1]= 1; YMat[1][2]= 0; YMat[1][3]= 0;
YMat[2][0]= Sy; YMat[2][1]= 0; YMat[2][2]= Cy; YMat[2][3]= 0;
YMat[3][0]= 0; YMat[3][1]= 0; YMat[3][2]= 0; YMat[3][3]= 1;
ZMat[0][0]= Cz; ZMat[0][1]= Sz; ZMat[0][2]= 0; ZMat[0][3]= 0;
ZMat[1][0]=-Sz; ZMat[1][1]= Cz; ZMat[1][2]= 0; ZMat[1][3]= 0;
ZMat[2][0]= 0; ZMat[2][1]= 0; ZMat[2][2]= 1; ZMat[2][3]= 0;
ZMat[3][0]= 0; ZMat[3][1]= 0; ZMat[3][2]= 0; ZMat[3][3]= 1;
MultMatrix ( Mat1, Matrix, XMat );
MultMatrix ( Mat2, Mat1, YMat );
MultMatrix ( Matrix, Mat2, ZMat );
} // End of Rotate for G3DENGINE
//*************************************************
//
// 3D Light
//
//*************************************************
G3DLIGHT::G3DLIGHT ()
{
} // End of Constructor for G3DLIGHT
G3DLIGHT::~G3DLIGHT ()
{
} // End of Destructor for G3DLIGHT
VOID G3DLIGHT::SetPosition ( double x, double y, double z )
{
Position.x = x;
Position.y = y;
Position.z = z;
} // End of SetPosition for G3DLIGHT
VOID G3DLIGHT::SetDirection ( double x, double y, double z )
{
double Magnitude;
Magnitude = x*x+y*y+z*z;
Magnitude = sqrt ( Magnitude );
if (Magnitude!=0)
{
Direction.x = x/Magnitude;
Direction.y = y/Magnitude;
Direction.z = z/Magnitude;
} // End if
else
{
Direction.x = x;
Direction.y = y;
Direction.z = z;
} // End if
} // End of SetDirection for G3DLIGHT
//*************************************************
//
// 3D Object
//
//*************************************************
G3DOBJECT::G3DOBJECT ()
{
NumPoints = 0;
Local3DList = NULL;
World3DList = NULL;
Camera3DList = NULL;
PointNormalList = NULL;
PointCountList = NULL;
IntensityList = NULL;
Scr2DList = NULL;
NumMeshes = 0;
MeshList = NULL;
Position.x = 0;
Position.y = 0;
Position.z = 0;
Angle.x = 0;
Angle.y = 0;
Angle.z = 0;
} // End of Constructor for G3DOBJECT
G3DOBJECT::~G3DOBJECT ()
{
if (Local3DList!=NULL)
{
delete Local3DList;
Local3DList = NULL;
} // End if
if (World3DList!=NULL)
{
delete World3DList;
World3DList = NULL;
} // End if
if (Camera3DList!=NULL)
{
delete Camera3DList;
Camera3DList = NULL;
} // End if
if (PointNormalList!=NULL)
{
delete PointNormalList;
PointNormalList = NULL;
} // End if
if (PointCountList!=NULL)
{
delete PointCountList;
PointCountList = NULL;
} // End if
if (IntensityList!=NULL)
{
delete IntensityList;
IntensityList = NULL;
} // End if
if (Scr2DList!=NULL)
{
delete Scr2DList;
Scr2DList = NULL;
} // End if
if (MeshList!=NULL)
{
delete MeshList;
MeshList = NULL;
} // End if
} // End of Destructor for G3DOBJECT
BOOLEAN G3DOBJECT::CreatePoints ( LONG Num )
{
if (Local3DList!=NULL)
delete Local3DList;
Local3DList = new POINT3D [Num];
if (Local3DList==NULL)
return FAILURE;
if (World3DList!=NULL)
delete World3DList;
World3DList = new POINT3D [Num];
if (World3DList==NULL)
return FAILURE;
if (Camera3DList!=NULL)
delete Camera3DList;
Camera3DList = new POINT3D [Num];
if (Camera3DList==NULL)
return FAILURE;
if (PointNormalList!=NULL)
delete PointNormalList;
PointNormalList = new POINT3D [Num];
if (PointNormalList==NULL)
return FAILURE;
if (PointCountList!=NULL)
delete PointCountList;
PointCountList = new BYTE [Num];
if (PointCountList==NULL)
return FAILURE;
if (IntensityList!=NULL)
delete IntensityList;
IntensityList = new LONG [Num];
if (IntensityList==NULL)
return FAILURE;
if (Scr2DList!=NULL)
delete Scr2DList;
Scr2DList = new POINT2D [Num];
if (Scr2DList==NULL)
return FAILURE;
NumPoints = Num;
return SUCCESS;
} // End of CreatePoints for G3DOBJECT
BOOLEAN G3DOBJECT::CreateMeshes ( LONG Num )
{
if (MeshList!=NULL)
delete MeshList;
MeshList = new MESH3D [Num];
if (MeshList==NULL)
return FAILURE;
LONG i;
for (i=0;i<Num;i++)
{
MeshList[i].Flags = 0;
} // End for
NumMeshes = Num;
return SUCCESS;
} // End of CreateMeshes for G3DOBJECT
VOID G3DOBJECT::TransformLocalToWorld ( MATRIX Matrix )
{
LONG i;
for (i=0;i<NumPoints;i++)
{
double x,y,z;
x = Local3DList[i].x;
y = Local3DList[i].y;
z = Local3DList[i].z;
World3DList[i].x = x * Matrix[0][0] +
y * Matrix[1][0] +
z * Matrix[2][0] +
Matrix[3][0] + Position.x;
World3DList[i].y = x * Matrix[0][1] +
y * Matrix[1][1] +
z * Matrix[2][1] +
Matrix[3][1] + Position.y;
World3DList[i].z = x * Matrix[0][2] +
y * Matrix[1][2] +
z * Matrix[2][2] +
Matrix[3][2] + Position.z;
} // End for
} // End of TransformLocalToWorld for G3DOBJECT
VOID G3DOBJECT::TransformWorldToCamera ( MATRIX Matrix )
{
LONG i;
double cz;
for (i=0;i<NumPoints;i++)
{
double x,y,z;
x = World3DList[i].x;
y = World3DList[i].y;
z = World3DList[i].z;
Camera3DList[i].x = x * Matrix[0][0] +
y * Matrix[1][0] +
z * Matrix[2][0] +
Matrix[3][0];
Camera3DList[i].y = x * Matrix[0][1] +
y * Matrix[1][1] +
z * Matrix[2][1] +
Matrix[3][1];
cz = Camera3DList[i].z = x * Matrix[0][2] +
y * Matrix[1][2] +
z * Matrix[2][2] +
Matrix[3][2];
if (i==0)
MinZ = MaxZ = cz;
else
{
if (cz<MinZ)
MinZ = cz;
else if (cz>MaxZ)
MaxZ = cz;
} // End else
} // End for
} // End of TransformWorldToCamera for G3DOBJECT
VOID G3DOBJECT::Project ( LONG Distance )
{
LONG i;
for (i=0;i<NumPoints;i++)
{
double z;
z = Camera3DList[i].z;
if (z == 0)
z = 0.1;
Scr2DList[i].x = Camera3DList[i].x*Distance / z;
Scr2DList[i].y = - (Camera3DList[i].y*Distance / z);
} // End for
} // End of Project for G3DOBJECT
VOID G3DOBJECT::SetPosition ( double x, double y, double z )
{
Position.x = x;
Position.y = y;
Position.z = z;
} // End of SetPosition for G3DOBJECT
VOID G3DOBJECT::SetAngle ( double xa, double ya, double za )
{
Angle.x = xa;
Angle.y = ya;
Angle.z = za;
} // End of SetAngle for G3DOBJECT
VOID G3DOBJECT::Move ( double x, double y, double z,
double xa, double ya, double za )
{
MATRIX Matrix;
Position.x += x;
Position.y += y;
Position.z += z;
Angle.x += xa;
Angle.y += ya;
Angle.z += za;
InitMatrix ( Matrix );
Rotate ( Matrix, -Angle.x, -Angle.y, -Angle.z );
TransformLocalToWorld ( Matrix );
} // End of Move for G3DOBJECT
VOID G3DOBJECT::GetMeshNormal ( MESH3D *Mesh )
{
double A,B,C;
double x1,y1,z1,x2,y2,z2,x3,y3,z3;
LONG *List;
LONG List0,List1,List2;
List = Mesh->Points;
List0 = List[0];
List1 = List[1];
List2 = List[2];
x1 = Camera3DList[List0].x;
y1 = Camera3DList[List0].y;
z1 = Camera3DList[List0].z;
x2 = Camera3DList[List1].x;
y2 = Camera3DList[List1].y;
z2 = Camera3DList[List1].z;
x3 = Camera3DList[List2].x;
y3 = Camera3DList[List2].y;
z3 = Camera3DList[List2].z;
// Take a cross product of two vectors
A = (y2-y1)*(z3-z1) - (z2-z1)*(y3-y1);
B = - ((x2-x1)*(z3-z1) - (z2-z1)*(x3-x1));
C = (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1);
if (Mesh->Flags&MESH_REVERSED)
{
A = -A;
B = -B;
C = -C;
} // End if
double Magnitude = A*A + B*B + C*C;
Magnitude = sqrt ( Magnitude );
if (Magnitude!=0)
{
A /= Magnitude;
B /= Magnitude;
C /= Magnitude;
} // End if
Mesh->A = A;
Mesh->B = B;
Mesh->C = C;
} // End of GetMeshNormal for G3DOBJECT
BOOLEAN G3DOBJECT::MeshVisible ( LONG Index )
{
MESH3D *Mesh;
double z1,z2,z3;
double MeshMinZ,MeshMaxZ;
LONG *List;
LONG List0,List1,List2;
Mesh = &(MeshList[Index]);
List = Mesh->Points;
List0 = List[0];
List1 = List[1];
List2 = List[2];
MeshMinZ = MeshMaxZ = z1 = Camera3DList[List0].z;
z2 = Camera3DList[List1].z;
if (z2<MeshMinZ)
MeshMinZ = z2;
else if (z2>MeshMaxZ)
MeshMaxZ = z2;
z3 = Camera3DList[List2].z;
if (z3<MeshMinZ)
MeshMinZ = z3;
else if (z3>MeshMaxZ)
MeshMaxZ = z3;
if (MeshMaxZ<MIN_Z_DISTANCE)
{
Mesh->Flags &= ~MESH_VISIBLE;
return FALSE;
} // End if
GetMeshNormal ( Mesh );
PointCountList[List0] ++;
PointNormalList[List0].x += Mesh->A;
PointNormalList[List0].y += Mesh->B;
PointNormalList[List0].z += Mesh->C;
PointCountList[List1] ++;
PointNormalList[List1].x += Mesh->A;
PointNormalList[List1].y += Mesh->B;
PointNormalList[List1].z += Mesh->C;
PointCountList[List2] ++;
PointNormalList[List2].x += Mesh->A;
PointNormalList[List2].y += Mesh->B;
PointNormalList[List2].z += Mesh->C;
Mesh->MinZ = MeshMinZ;
Mesh->MaxZ = MeshMaxZ;
// Take a dot product
double Product;
double x1,y1;
x1 = Camera3DList[List0].x;
y1 = Camera3DList[List0].y;
Product = Mesh->A*x1+Mesh->B*y1+Mesh->C*z1;
if (Product<0)
{
Mesh->Flags &= ~MESH_VISIBLE;
return FALSE;
} // End if
Mesh->Flags |= MESH_VISIBLE;
return TRUE;
} // End of MeshVisible for G3DOBJECT
VOID G3DOBJECT::ProcessMeshes ()
{
LONG i;
for (i=0;i<NumPoints;i++)
{
PointCountList[i] = 0;
PointNormalList[i].x = 0;
PointNormalList[i].y = 0;
PointNormalList[i].z = 0;
} // End for
for (i=0;i<NumMeshes;i++)
{
MeshVisible ( i );
} // End for
} // End of ProcessMeshes
VOID G3DOBJECT::ComputePointIntensity ( G3DLIGHT **LightList )
{
LONG i;
G3DLIGHT *Light;
double Product;
Light = LightList[LightSource];
for (i=0;i<NumPoints;i++)
{
double Count;
double x,y,z;
Count = (double)PointCountList[i];
x = PointNormalList[i].x;
y = PointNormalList[i].y;
z = PointNormalList[i].z;
if (Count!=0)
{
x /= Count;
y /= Count;
z /= Count;
} // End if
// Do Cross Product
Product = x*Light->Direction.x+
y*Light->Direction.y+
z*Light->Direction.z;
LONG Level;
Level = Product*(MaxShadeNumber);
if (Level<0)
Level = 0;
else if (Level>(MaxShadeNumber-256))
Level = MaxShadeNumber-256;
IntensityList[i] = Level;
} // End for
} // End of ComputePointIntensity for G3DOBJECT
VOID G3DOBJECT::Init ()
{
} // End of Init for G3DOBJECT
//*************************************************
//
// 3D World
//
//*************************************************
G3DWORLD::G3DWORLD ()
{
NumObjects = 0;
ObjectList = NULL;
NumLights = 0;
LightList = NULL;
TextureList = NULL;
NumTextures = 0;
} // End of Constructor for G3DWORLD
G3DWORLD::~G3DWORLD ()
{
LONG i;
if (ObjectList!=NULL)
{
for (i=0;i<NumObjects;i++)
{
delete ObjectList[i];
} // End for
delete ObjectList;
} // End if
ObjectList = NULL;
if (LightList!=NULL)
{
for (i=0;i<NumLights;i++)
{
delete LightList[i];
} // End for
delete LightList;
} // End if
LightList = NULL;
if (TextureList!=NULL)
{
for (i=0;i<NumTextures;i++)
{
delete TextureList[i];
} // End for
delete TextureList;
TextureList = NULL;
} // End if
} // End of Destructor for G3DWORLD
BOOLEAN G3DWORLD::CreateTextures ( LONG Num )
{
NumTextures = Num;
LONG i;
if (TextureList!=NULL)
{
for (i=0;i<NumTextures;i++)
delete TextureList[i];
} // End if
delete TextureList;
NumTextures = Num;
TextureList = new IMAGE * [NumTextures];
if (TextureList==NULL)
return FAILURE;
for (i=0;i<NumTextures;i++)
{
TextureList[i] = new IMAGE ();
if (TextureList[i]==NULL)
return FAILURE;
} // End for
return SUCCESS;
} // End of CreateTextures for G3DWORLD
BOOLEAN G3DWORLD::CreateObjects ( LONG Num )
{
INT i;
if (ObjectList!=NULL)
{
for (i=0;i<NumObjects;i++)
{
delete ObjectList[i];
} // End for
delete ObjectList;
} // End if
ObjectList = new G3DOBJECT* [Num];
if (ObjectList==NULL)
return FAILURE;
NumObjects = Num;
for (i=0;i<NumObjects;i++)
{
ObjectList[i] = new G3DOBJECT ();
} // End for
return SUCCESS;
} // End of CreateObjects for G3DWORLD
BOOLEAN G3DWORLD::CreateLights ( LONG Num )
{
INT i;
if (LightList!=NULL)
{
for (i=0;i<NumLights;i++)
{
delete LightList[i];
} // End for
delete LightList;
} // End if
LightList = new G3DLIGHT* [Num];
if (LightList==NULL)
return FAILURE;
NumLights = Num;
for (i=0;i<NumLights;i++)
{
LightList[i] = new G3DLIGHT ();
} // End for
return SUCCESS;
} // End of CreateLights for G3DWORLD
LONG G3DWORLD::GetMeshIntensity ( G3DOBJECT *Object, MESH3D *Mesh )
{
double A,B,C;
G3DLIGHT *Light;
Light = LightList[Object->GetLightSource ()];
A = Mesh->A;
B = Mesh->B;
C = Mesh->C;
// Do Cross Product
double Product;
LONG Intensity;
Product = A*Light->Direction.x+
B*Light->Direction.y+
C*Light->Direction.z;
if (Product<=0)
return 0;
else
{
Intensity = Product*MaxShadeNumber;
if (Intensity<0)
Intensity = 0;
else if (Intensity>MaxShadeNumber-256)
Intensity = MaxShadeNumber-256;
} // End else
return Intensity;
} // End of GetMeshIntensity for G3DWORLD
//*************************************************
//
// 3D Viewer
//
//*************************************************
G3DCAMERA::G3DCAMERA ()
{
SetPosition ( 0, 0, 0 );
SetAngle ( 0, 0, 0 );
} // End of Constructor for G3DCAMERA
G3DCAMERA::~G3DCAMERA ()
{
} // End of Destructor for G3DCAMERA
VOID G3DCAMERA::SetPosition ( double x, double y, double z )
{
Position.x = x;
Position.y = y;
Position.z = z;
} // End of SetPosition for G3DCAMERA
VOID G3DCAMERA::SetAngle ( double xa, double ya, double za )
{
Angle.x = xa;
Angle.y = ya;
Angle.z = za;
} // End of SetAngle for G3DCAMERA
VOID G3DCAMERA::MovePosition ( double x, double y, double z )
{
Position.x += x;
Position.y += y;
Position.z += z;
} // End of MovePosition for G3DCAMERA
VOID G3DCAMERA::MoveAngle ( double xa, double ya, double za )
{
Angle.x += xa;
Angle.y += ya;
Angle.z += za;
} // End of MoveAngle for G3DCAMERA
//*************************************************
//
// 3D Graphics Engine
//
//*************************************************
G3DENGINE::G3DENGINE ()
{
Camera = new G3DCAMERA ();
World = NULL;
NumVisibleMeshes = 0;
VisibleMeshes = NULL;
ShadeTable = NULL;
ShadeMethod = SHADE_GOURAUD;
SurfaceMethod = SURFACE_TEXTURE;
TextureList = NULL;
} // End of Constructor for G3DENGINE
G3DENGINE::~G3DENGINE ()
{
if (Camera!=NULL)
delete Camera;
Camera = NULL;
if (VisibleMeshes!=NULL)
delete VisibleMeshes;
VisibleMeshes = NULL;
TextureList = NULL;
} // End of Destructor for G3DENGINE
VOID G3DENGINE::SetWorld ( G3DWORLD *NewWorld )
{
if (NewWorld==NULL)
return;
World = NewWorld;
LONG NumObjects;
LONG i;
G3DOBJECT **ObjectList;
LONG NumMeshes;
NumObjects = World->GetNumObjects ();
ObjectList = World->GetObjectList ();
NumMeshes = 0;
for (i=0;i<NumObjects;i++)
{
NumMeshes += ObjectList[i]->GetNumMeshes ();
ObjectList[i]->Init ();
ObjectList[i]->Move ( 0, 0, 0, 0, 0, 0 );
} // End for
if (VisibleMeshes!=NULL)
delete VisibleMeshes;
VisibleMeshes = new MESHNODE [NumMeshes*2];
TextureList = World->GetTextureList ();
} // End of SetWorld for G3DENGINE
VOID G3DENGINE::Transform ()
{
if (World==NULL)
return;
LONG NumObjects;
G3DOBJECT **ObjectList;
NumObjects = World->GetNumObjects ();
ObjectList = World->GetObjectList ();
LONG i;
for (i=0;i<NumObjects;i++)
{
ObjectList[i]->TransformWorldToCamera ( MasterMatrix );
} // End for
} // End of Transform for G3DENGINE
INT MIDDLEPOINTTABLE[3][3] = { { 1, 2, 1 }, { 2, 0, 0 }, { 1, 0, 0 } };
typedef VOID (*DrawMeshType) ( BYTE *Buffer, LONG AddDest, BYTE Color, LONG Length );
VOID G3DENGINE::DrawTriMesh ( IMAGE *Dest, DRAWPOINT2D *Points, BYTE Color,
IMAGE *Image, LONG ILevel, LONG Flags )
{
LONG MinX,MaxX,MinY,MaxY;
LONG i,High,Middle,Low;
// Sort the Points in order of high to low in y coord.
MinX = MaxX = Points[0].x;
MinY = MaxY = Points[0].y;
Low = High = 0;
for (i=1;i<3;i++)
{
LONG x,y;
x = Points[i].x;
y = Points[i].y;
if (x<MinX)
MinX = x;
else if (x>MaxX)
MaxX = x;
if (y<MinY)
{
MinY = y;
High = i;
} // End if
else if (y>MaxY)
{
MaxY = y;
Low = i;
} // End if
} // End for
RECTANGLE ViewPort;
BOOLEAN Clipped = FALSE;
ViewPort = Dest->GetViewPort ();
// Check for if clipping is necessary
if (MinX>ViewPort.x2)
return;
if (MinY>ViewPort.y2)
return;
if (MaxX<ViewPort.x1)
return;
if (MaxY<ViewPort.y1)
return;
if (MinX<ViewPort.x1)
{
Clipped = TRUE;
SetViewRegion ( ViewPort.x1, ViewPort.x2 );
} // End if
else if (MaxX>ViewPort.x2)
{
Clipped = TRUE;
SetViewRegion ( ViewPort.x1, ViewPort.x2 );
} // End else if
Middle = MIDDLEPOINTTABLE[High][Low];
INT Case;
if (Points[Low].y==Points[Middle].y)
Case = 1;
else if (Points[High].y==Points[Middle].y)
Case = 2;
else
{
Case = 3;
} // End else
LONG Length,Diff;
LONG StartY;
LONG x1,x2,x3,x4;
LONG u1,u2,u3,u4;
LONG v1,v2,v3,v4;
LONG I1,I2,I3,I4;
LONG Dx1,Dx2,Dx3,Dx4;
LONG DI1,DI2,DI3,DI4;
LONG Du1,Du2,Du3,Du4;
LONG Dv1,Dv2,Dv3,Dv4;
LONG Dy1,Dy2,Dy3;
INT Left,Right;
BYTE *Buffer;
LONG Temp;
BOOLEAN IsTexture,IsGouraud,IsFlat;
DrawMeshType DrawMesh;
if (Flags&MESH_FLAT)
IsFlat = TRUE;
else
IsFlat = FALSE;
if (Flags&MESH_GOURAUD)
IsGouraud = TRUE;
else
IsGouraud = FALSE;
if (Flags&MESH_TEXTURE)
IsTexture = TRUE;
else
IsTexture = FALSE;
if (IsTexture)
{
if (Clipped)
{
if (IsGouraud)
DrawMesh = DrawClippedGTex;
else if (IsFlat)
DrawMesh = DrawClippedFTex;
else
DrawMesh = DrawClippedTex;
} // End if
else
{
if (IsGouraud)
DrawMesh = DrawGTexTriangle;
else if (IsFlat)
{
SetFShadeTable ( ShadeTable->GetTable() + (ILevel&0xFF00) );
DrawMesh = DrawFTexTriangle;
} // End else if
else
DrawMesh = DrawTexTriangle;
} // End else
} // End if
else
{
if (Clipped)
{
if (IsGouraud)
DrawMesh = DrawClippedGShade;
else
DrawMesh = DrawClippedTriangle;
} // End if
else
{
if (IsGouraud)
DrawMesh = DrawGShadeTriangle;
else
DrawMesh = DrawSimpleTriangle;
} // End else
} // End else
switch (Case)
{
case 1 :
if (Points[Middle].x<=Points[Low].x)
{
Left = Middle;
Right = Low;
} // End if
else
{
Left = Low;
Right = Middle;
} // End if
Dx1 = (Points[Left].x-Points[High].x)<<16;
Dx2 = (Points[Right].x-Points[High].x)<<16;
Dy1 = Points[Left].y-Points[High].y+1;
Dy2 = Points[Right].y-Points[High].y+1;
Dx1 = Dx1 / Dy1;
Dx2 = Dx2 / Dy2;
x1 = Points[High].x <<16;
x2 = x1;
if (IsTexture)
{
Du1 = ((LONG)Points[Left].u-Points[High].u)<<16;
Du2 = ((LONG)Points[Right].u-Points[High].u)<<16;
Dv1 = ((LONG)Points[Left].v-Points[High].v)<<16;
Dv2 = ((LONG)Points[Right].v-Points[High].v)<<16;
Du1 = Du1 / Dy1;
Du2 = Du2 / Dy2;
Dv1 = Dv1 / Dy1;
Dv2 = Dv2 / Dy2;
u1 = (LONG)Points[High].u << 16;
u2 = u1;
v1 = (LONG)Points[High].v << 16;
v2 = v1;
} // End if
if (IsGouraud)
{
DI1 = ((LONG)Points[Left].Intensity-(LONG)Points[High].Intensity)<<16;
DI2 = ((LONG)Points[Right].Intensity-(LONG)Points[High].Intensity)<<16;
DI1 = DI1 / Dy1;
DI2 = DI2 / Dy2;
I1 = (LONG)Points[High].Intensity << 16;
I2 = I1;
} // End if
Length = Points[Low].y-Points[High].y+1;
Diff = 0;
if (Points[High].y<ViewPort.y1)
{
Diff = ViewPort.y1-Points[High].y;
StartY = ViewPort.y1;
Length -= Diff;
x1 += Dx1*Diff;
x2 += Dx2*Diff;
if (IsTexture)
{
u1 += Du1*Diff;
u2 += Du2*Diff;
v1 += Dv1*Diff;
v2 += Dv2*Diff;
} // End if
if (IsGouraud)
{
I1 += DI1*Diff;
I2 += DI2*Diff;
} // End if
} // End if
else
StartY = Points[High].y;
if (Points[Low].y>ViewPort.y2)
Length -= Points[Low].y - ViewPort.y2;
if (Length>0)
{
SetLeftRight ( x1, x2, Dx1, Dx2 );
Buffer = Dest->SetOffset ( 0, StartY );
if (IsTexture)
{
SetUData ( u1, u2, Du1, Du2 );
SetVData ( v1, v2, Dv1, Dv2 );
SetImageBuffer ( Image->GetBuffer () );
} // End if
if (IsGouraud)
{
SetIntensities ( I1, I2, DI1, DI2 );
SetGShadeTable ( ShadeTable->GetTable() );
} // End if
DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
} // End if
break;
case 2 :
if (Points[High].x<=Points[Middle].x)
{
Left = High;
Right = Middle;
} // End if
else
{
Left = Middle;
Right = High;
} // End if
Dx1 = (Points[Low].x-Points[Left].x)<<16;
Dx2 = (Points[Low].x-Points[Right].x)<<16;
Dy1 = Points[Low].y-Points[Left].y+1;
Dy2 = Points[Low].y-Points[Right].y+1;
Dx1 = Dx1 / Dy1;
Dx2 = Dx2 / Dy2;
x1 = Points[Left].x <<16;
x2 = Points[Right].x <<16;
if (IsTexture)
{
Du1 = ((LONG)Points[Low].u-Points[Left].u)<<16;
Du2 = ((LONG)Points[Low].u-Points[Right].u)<<16;
Dv1 = ((LONG)Points[Low].v-Points[Left].v)<<16;
Dv2 = ((LONG)Points[Low].v-Points[Right].v)<<16;
Du1 = Du1 / Dy1;
Du2 = Du2 / Dy2;
Dv1 = Dv1 / Dy1;
Dv2 = Dv2 / Dy2;
u1 = (LONG)Points[Left].u <<16;
u2 = (LONG)Points[Right].u <<16;
v1 = (LONG)Points[Left].v <<16;
v2 = (LONG)Points[Right].v <<16;
} // End if
if (IsGouraud)
{
DI1 = ((LONG)Points[Low].Intensity-(LONG)Points[Left].Intensity)<<16;
DI2 = ((LONG)Points[Low].Intensity-(LONG)Points[Right].Intensity)<<16;
DI1 = DI1 / Dy1;
DI2 = DI2 / Dy2;
I1 = (LONG)Points[Left].Intensity << 16;
I2 = (LONG)Points[Right].Intensity << 16;
} // End if
Length = Points[Low].y-Points[High].y+1;
Diff = 0;
if (Points[High].y<ViewPort.y1)
{
Diff = ViewPort.y1-Points[High].y;
StartY = ViewPort.y1;
Length -= Diff;
x1 += Dx1*Diff;
x2 += Dx2*Diff;
if (IsTexture)
{
u1 += Du1*Diff;
u2 += Du2*Diff;
v1 += Dv1*Diff;
v2 += Dv2*Diff;
} // End if
if (IsGouraud)
{
I1 += DI1*Diff;
I2 += DI2*Diff;
} // End if
} // End i
else
StartY = Points[High].y;
if (Points[Low].y>ViewPort.y2)
Length -= Points[Low].y - ViewPort.y2;
if (Length>0)
{
SetLeftRight ( x1, x2, Dx1, Dx2 );
Buffer = Dest->SetOffset ( 0, StartY );
if (IsTexture)
{
SetUData ( u1, u2, Du1, Du2 );
SetVData ( v1, v2, Dv1, Dv2 );
SetImageBuffer ( Image->GetBuffer () );
} // End if
if (IsGouraud)
{
SetIntensities ( I1, I2, DI1, DI2 );
SetGShadeTable ( ShadeTable->GetTable() );
} // End if
DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
} // End if
break;
case 3 :
Dx1 = (Points[Middle].x-Points[High].x)<<16;
Dx2 = (Points[Low].x-Points[High].x)<<16;
Dx3 = (Points[Low].x-Points[Middle].x)<<16;
Dy1 = Points[Middle].y-Points[High].y;
Dy2 = Points[Low].y-Points[High].y+1;
Dy3 = Points[Low].y-Points[Middle].y+1;
Dx1 = Dx1 / Dy1;
Dx2 = Dx2 / Dy2;
Dx3 = Dx3 / Dy3;
Dx4 = Dx2;
x1 = Points[High].x <<16;
x2 = Points[High].x <<16;
x3 = Points[Middle].x << 16;
x4 = Points[High].x << 16;
x4 += Dy1*Dx4;
if (IsTexture)
{
Du1 = ((LONG)Points[Middle].u-Points[High].u)<<16;
Du2 = ((LONG)Points[Low].u-Points[High].u)<<16;
Du3 = ((LONG)Points[Low].u-Points[Middle].u)<<16;
Dv1 = ((LONG)Points[Middle].v-Points[High].v)<<16;
Dv2 = ((LONG)Points[Low].v-Points[High].v)<<16;
Dv3 = ((LONG)Points[Low].v-Points[Middle].v)<<16;
Du1 = Du1 / Dy1;
Du2 = Du2 / Dy2;
Du3 = Du3 / Dy3;
Du4 = Du2;
Dv1 = Dv1 / Dy1;
Dv2 = Dv2 / Dy2;
Dv3 = Dv3 / Dy3;
Dv4 = Dv2;
u1 = (LONG)Points[High].u <<16;
u2 = (LONG)Points[High].u <<16;
u3 = (LONG)Points[Middle].u <<16;
u4 = (LONG)Points[High].u <<16;
u4 += Dy1*Du4;
v1 = (LONG)Points[High].v <<16;
v2 = (LONG)Points[High].v <<16;
v3 = (LONG)Points[Middle].v <<16;
v4 = (LONG)Points[High].v <<16;
v4 += Dy1*Dv4;
} // End if
if (IsGouraud)
{
DI1 = ((LONG)Points[Middle].Intensity-(LONG)Points[High].Intensity)<<16;
DI2 = ((LONG)Points[Low].Intensity-(LONG)Points[High].Intensity)<<16;
DI3 = ((LONG)Points[Low].Intensity-(LONG)Points[Middle].Intensity)<<16;
DI1 = DI1 / Dy1;
DI2 = DI2 / Dy2;
DI3 = DI3 / Dy3;
DI4 = DI2;
I1 = (LONG)Points[High].Intensity << 16;
I2 = (LONG)Points[High].Intensity << 16;
I3 = (LONG)Points[Middle].Intensity << 16;
I4 = (LONG)Points[High].Intensity << 16;
I4 += Dy1*DI4;
} // End if
if (Dx1>Dx2)
{
Temp = Dx1;
Dx1 = Dx2;
Dx2 = Temp;
Temp = Du1;
Du1 = Du2;
Du2 = Temp;
Temp = Dv1;
Dv1 = Dv2;
Dv2 = Temp;
Temp = DI1;
DI1 = DI2;
DI2 = Temp;
} // End if
if (Points[Middle].y>ViewPort.y1)
{
Length = Points[Middle].y-Points[High].y;
Diff = 0;
if (Points[High].y<ViewPort.y1)
{
Diff = ViewPort.y1-Points[High].y;
StartY = ViewPort.y1;
Length -= Diff;
x1 += Dx1*Diff;
x2 += Dx2*Diff;
if (IsTexture)
{
u1 += Du1*Diff;
u2 += Du2*Diff;
v1 += Dv1*Diff;
v2 += Dv2*Diff;
} // End if
if (IsGouraud)
{
I1 += DI1*Diff;
I2 += DI2*Diff;
} // End if
} // End if
else
StartY = Points[High].y;
if (Points[Middle].y-1>ViewPort.y2)
Length -= (Points[Middle].y-1) - ViewPort.y2;
if (Length>0)
{
SetLeftRight ( x1, x2, Dx1, Dx2 );
Buffer = Dest->SetOffset ( 0, StartY );
if (IsTexture)
{
SetUData ( u1, u2, Du1, Du2 );
SetVData ( v1, v2, Dv1, Dv2 );
SetImageBuffer ( Image->GetBuffer () );
} // End if
if (IsGouraud)
{
SetIntensities ( I1, I2, DI1, DI2 );
SetGShadeTable ( ShadeTable->GetTable() );
} // End if
DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
} // End if
} // End if
if (Points[Middle].y<=ViewPort.y2)
{
Length = Points[Low].y-Points[Middle].y+1;
Diff = 0;
if (Points[Middle].y<ViewPort.y1)
{
Diff = ViewPort.y1-Points[Middle].y;
StartY = ViewPort.y1;
Length -= Diff;
x3 += Dx3*Diff;
x4 += Dx4*Diff;
if (IsTexture)
{
u3 += Du3*Diff;
u4 += Du4*Diff;
v3 += Dv3*Diff;
v4 += Dv4*Diff;
} // End if
if (IsGouraud)
{
I3 += DI3*Diff;
I4 += DI4*Diff;
} // End if
} // End if
else
StartY = Points[Middle].y;
if (Points[Low].y>ViewPort.y2)
Length -= Points[Low].y - ViewPort.y2;
if (x3>x4)
{
Temp = x3;
x3 = x4;
x4 = Temp;
Temp = Dx3;
Dx3 = Dx4;
Dx4 = Temp;
Temp = u3;
u3 = u4;
u4 = Temp;
Temp = v3;
v3 = v4;
v4 = Temp;
Temp = Du3;
Du3 = Du4;
Du4 = Temp;
Temp = Dv3;
Dv3 = Dv4;
Dv4 = Temp;
Temp = I3;
I3 = I4;
I4 = Temp;
Temp = DI3;
DI3 = DI4;
DI4 = Temp;
} // End if
if (Length>0)
{
SetLeftRight ( x3, x4, Dx3, Dx4 );
Buffer = Dest->SetOffset ( 0, StartY );
if (IsTexture)
{
SetUData ( u3, u4, Du3, Du4 );
SetVData ( v3, v4, Dv3, Dv4 );
SetImageBuffer ( Image->GetBuffer () );
} // End if
if (IsGouraud)
{
SetIntensities ( I3, I4, DI3, DI4 );
} // End if
DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
} // End if
} // End if
break;
} // End case
} // End of DrawTriMesh for G3DENGINE
VOID G3DENGINE::UpdateWorld ()
{
InitMatrix ( MasterMatrix );
POINT3D Position;
POINT3D Angle;
Position = Camera->GetPosition ();
Angle = Camera->GetAngle ();
Translate ( MasterMatrix, -Position.x, -Position.y, -Position.z );
Rotate ( MasterMatrix, -Angle.x, -Angle.y, -Angle.z );
Transform ();
} // End of UpdateWorld for G3DENGINE
BOOLEAN G3DENGINE::CreateDatabase ( STRING FileName, double x, double y, double z )
{
G3DWORLD *NewWorld;
INT i;
NewWorld = new G3DWORLD ();
NewWorld->CreateObjects ( 1 );
NewWorld->CreateTextures ( 1 );
NewWorld->CreateLights ( 1 );
G3DLIGHT **LightList = NewWorld->GetLightList ();
LightList[0]->SetPosition ( 0, 0, 0 );
LightList[0]->SetDirection ( 1, 0, 1 );
IMAGE **Images;
Images = NewWorld->GetTextureList ();
Grafix.LoadImage ( "texture.pcx", Images[0], NULL );
G3DOBJECT **Object;
Object = NewWorld->GetObjectList ();
Object[0]->SetPosition ( x, y, z );
Object[0]->SetLightSource ( 0 );
LINKEDLIST<POINT3D> *ListPoint = new LINKEDLIST<POINT3D> ();
LINKEDLIST<MESH3D> *ListMesh = new LINKEDLIST<MESH3D> ();
if (LoadASC ( FileName, ListPoint, ListMesh )==FAILURE)
return FAILURE;
Object[0]->CreatePoints ( ListPoint->GetNumObjects() );
Object[0]->CreateMeshes ( ListMesh->GetNumObjects() );
POINT3D *Points;
MESH3D *Mesh;
LISTOBJECT<POINT3D> *PointPtr;
LISTOBJECT<MESH3D> *MeshPtr;
Points = Object[0]->GetLocal3DList ();
Mesh = Object[0]->GetMeshList ();
PointPtr = ListPoint->GetHead ();
for (i=0;i<ListPoint->GetNumObjects();i++)
{
Points[i] = PointPtr->Data;
PointPtr = PointPtr->NextObject;
} // End for
MeshPtr = ListMesh->GetHead ();
for (i=0;i<ListMesh->GetNumObjects();i++)
{
Mesh[i].Points[0] = MeshPtr->Data.Points[0];
Mesh[i].Points[1] = MeshPtr->Data.Points[1];
Mesh[i].Points[2] = MeshPtr->Data.Points[2];
Mesh[i].Flags = MESH_TEXTURE | MESH_GOURAUD | MESH_REVERSED;
Mesh[i].Surface = 255;
Mesh[i].Texture = 0;
Mesh[i].TexPoints[0].u = 255;
Mesh[i].TexPoints[0].v = 0;
Mesh[i].TexPoints[1].u = 0;
Mesh[i].TexPoints[1].v = 255;
Mesh[i].TexPoints[2].u = 255;
Mesh[i].TexPoints[2].v = 255;
MeshPtr = MeshPtr->NextObject;
} // End for
delete ListPoint;
delete ListMesh;
if (World!=NULL)
delete World;
World = NULL;
SetWorld ( NewWorld );
return SUCCESS;
} // End of CreateDatabase for G3DENGINE
VOID G3DENGINE::SetViewData ( LONG NewCenterX, LONG NewCenterY, LONG NewDistance )
{
CenterX = NewCenterX;
CenterY = NewCenterY;
Distance = NewDistance;
} // End of SetViewData for G3DENGINE
VOID G3DENGINE::ZIntersect ( CLIPPOINT3D *In, CLIPPOINT3D *Out, CLIPPOINT3D *Intersect, LONG Flags )
{
double Ratio;
Ratio = (double)(MIN_Z_DISTANCE-Out->z)/(double)(In->z-Out->z);
Intersect->x = (double)(In->x-Out->x)*Ratio + Out->x;
Intersect->y = (double)(In->y-Out->y)*Ratio + Out->y;
Intersect->z = MIN_Z_DISTANCE;
if (Flags&MESH_GOURAUD)
{
Intersect->Intensity = (double)(In->Intensity-Out->Intensity)*Ratio +
Out->Intensity;
} // End if
if (Flags&MESH_TEXTURE)
{
Intersect->u = (double)(In->u-Out->u)*Ratio + Out->u;
Intersect->v = (double)(In->v-Out->v)*Ratio + Out->v;
} // End if
} // End of ZIntersect for G3DENGINE
INT G3DENGINE::ZClip ( CLIPPOINT3D *SrcPoints, CLIPPOINT3D *PolyPoints, LONG Flags )
{
CLIPPOINT3D P1,P2,I;
INT i;
INT NumPts;
P1 = SrcPoints[2];
NumPts = 0;
for (i=0;i<3;i++)
{
P2 = SrcPoints[i];
if (P2.z>=MIN_Z_DISTANCE)
{
if (P1.z<MIN_Z_DISTANCE)
{
ZIntersect ( &P2, &P1, &I, Flags );
PolyPoints[NumPts++] = I;
PolyPoints[NumPts++] = P2;
} // End if
else
{
PolyPoints[NumPts++] = P2;
} // End else
} // End if
else
{
if (P1.z>=MIN_Z_DISTANCE)
{
ZIntersect ( &P1, &P2, &I, Flags );
PolyPoints[NumPts++] = I;
} // End if
} // End else
P1 = P2;
} // End for
return NumPts;
} // End of ZClip for G3DENGINE
VOID G3DENGINE::DisplayMesh ( G3DOBJECT *Object, MESH3D *Mesh )
{
POINT2D *Points;
LONG *IntensityList;
LONG *List;
Points = Object->GetScr2DList ();
List = Mesh->Points;
Grafix.FGColor = Mesh->Surface;
DRAWPOINT2D DrawPoints[3];
SHORT Flags = Mesh->Flags;
if (SurfaceMethod==SURFACE_SOLID)
{
Flags &= ~MESH_TEXTURE;
Flags |= MESH_SOLID;
} // End if
else if (SurfaceMethod<SURFACE_SOLID)
{
Flags &= ~MESH_TEXTURE;
Flags &= ~MESH_SOLID;
} // End else if
if (ShadeMethod==SHADE_FLAT)
{
Flags &= ~MESH_GOURAUD;
Flags |= MESH_FLAT;
} // End if
else if (ShadeMethod<SHADE_FLAT)
{
Flags &= ~MESH_GOURAUD;
Flags &= ~MESH_FLAT;
} // End else if
BYTE Color;
BYTE *Table;
LONG Intensity;
IMAGE *Texture=NULL;
if (Mesh->MinZ>=MIN_Z_DISTANCE)
{
if (((Flags&MESH_SOLID)==0)&& // Wireframe
((Flags&MESH_TEXTURE)==0))
{
Grafix.DrawLine ( Dest, Points[List[0]].x+CenterX, Points[List[0]].y+CenterY,
Points[List[1]].x+CenterX, Points[List[1]].y+CenterY );
Grafix.DrawLine ( Dest, Points[List[1]].x+CenterX, Points[List[1]].y+CenterY,
Points[List[2]].x+CenterX, Points[List[2]].y+CenterY );
Grafix.DrawLine ( Dest, Points[List[2]].x+CenterX, Points[List[2]].y+CenterY,
Points[List[0]].x+CenterX, Points[List[0]].y+CenterY );
} // End if
else if (Flags&MESH_SOLID) // Solid Color
{
DrawPoints[0].x = Points[List[0]].x + CenterX;
DrawPoints[0].y = Points[List[0]].y + CenterY;
DrawPoints[1].x = Points[List[1]].x + CenterX;
DrawPoints[1].y = Points[List[1]].y + CenterY;
DrawPoints[2].x = Points[List[2]].x + CenterX;
DrawPoints[2].y = Points[List[2]].y + CenterY;
if (Flags&MESH_FLAT)
{
if (ShadeTable==NULL)
Color = Mesh->Surface;
else
{
Table = ShadeTable->GetTable();
Intensity = World->GetMeshIntensity ( Object, Mesh );
Color = Table[(Intensity&0xFF00)+Mesh->Surface];
} // End else
} // End if
else if (Flags&MESH_GOURAUD)
{
IntensityList = Object->GetIntensityList ();
DrawPoints[0].Intensity = IntensityList[List[0]];
DrawPoints[1].Intensity = IntensityList[List[1]];
DrawPoints[2].Intensity = IntensityList[List[2]];
Color = Mesh->Surface;
} // End if
else
{
Color = Mesh->Surface;
} // End else
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End else if
else if (Flags&MESH_TEXTURE)
{
if (TextureList==NULL)
return;
Texture = TextureList[Mesh->Texture];
DrawPoints[0].x = Points[List[0]].x + CenterX;
DrawPoints[0].y = Points[List[0]].y + CenterY;
DrawPoints[1].x = Points[List[1]].x + CenterX;
DrawPoints[1].y = Points[List[1]].y + CenterY;
DrawPoints[2].x = Points[List[2]].x + CenterX;
DrawPoints[2].y = Points[List[2]].y + CenterY;
DrawPoints[0].u = Mesh->TexPoints[0].u;
DrawPoints[0].v = Mesh->TexPoints[0].v;
DrawPoints[1].u = Mesh->TexPoints[1].u;
DrawPoints[1].v = Mesh->TexPoints[1].v;
DrawPoints[2].u = Mesh->TexPoints[2].u;
DrawPoints[2].v = Mesh->TexPoints[2].v;
if (Flags&MESH_FLAT)
{
Intensity = World->GetMeshIntensity ( Object, Mesh );
} // End if
else if (Flags&MESH_GOURAUD)
{
IntensityList = Object->GetIntensityList ();
DrawPoints[0].Intensity = IntensityList[List[0]];
DrawPoints[1].Intensity = IntensityList[List[1]];
DrawPoints[2].Intensity = IntensityList[List[2]];
} // End if
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End else if
} // End if
else
{
CLIPPOINT3D Src[3];
CLIPPOINT3D Clipped[4];
POINT3D *WPoints;
INT NumPts;
WPoints = Object->GetCamera3DList ();
Src[0].x=WPoints[List[0]].x; Src[0].y=WPoints[List[0]].y; Src[0].z=WPoints[List[0]].z;
Src[1].x=WPoints[List[1]].x; Src[1].y=WPoints[List[1]].y; Src[1].z=WPoints[List[1]].z;
Src[2].x=WPoints[List[2]].x; Src[2].y=WPoints[List[2]].y; Src[2].z=WPoints[List[2]].z;
if (Flags&MESH_GOURAUD)
{
IntensityList = Object->GetIntensityList ();
Src[0].Intensity = IntensityList[List[0]];
Src[1].Intensity = IntensityList[List[1]];
Src[2].Intensity = IntensityList[List[2]];
} // End if
if (Flags&MESH_TEXTURE)
{
Src[0].u=Mesh->TexPoints[0].u; Src[0].v=Mesh->TexPoints[0].v;
Src[1].u=Mesh->TexPoints[1].u; Src[1].v=Mesh->TexPoints[1].v;
Src[2].u=Mesh->TexPoints[2].u; Src[2].v=Mesh->TexPoints[2].v;
} // End if
NumPts = ZClip ( Src, Clipped, Flags );
LONG x1,y1,x2,y2,x3,y3,x4,y4;
x1 = Clipped[0].x*Distance/Clipped[0].z + CenterX;
y1 = -Clipped[0].y*Distance/Clipped[0].z + CenterY;
x2 = Clipped[1].x*Distance/Clipped[1].z + CenterX;
y2 = -Clipped[1].y*Distance/Clipped[1].z + CenterY;
x3 = Clipped[2].x*Distance/Clipped[2].z + CenterX;
y3 = -Clipped[2].y*Distance/Clipped[2].z + CenterY;
if (NumPts==4)
{
x4 = Clipped[3].x*Distance/Clipped[3].z + CenterX;
y4 = -Clipped[3].y*Distance/Clipped[3].z + CenterY;
} // End if
if (((Flags&MESH_SOLID)==0)&& // Wireframe
((Flags&MESH_TEXTURE)==0))
{
if (NumPts==3)
{
Grafix.DrawLine ( Dest, x1, y1, x2, y2 );
Grafix.DrawLine ( Dest, x2, y2, x3, y3 );
Grafix.DrawLine ( Dest, x3, y3, x1, y1 );
} // End if
else
{
Grafix.DrawLine ( Dest, x1, y1, x2, y2 );
Grafix.DrawLine ( Dest, x2, y2, x3, y3 );
Grafix.DrawLine ( Dest, x3, y3, x4, y4 );
Grafix.DrawLine ( Dest, x4, y4, x1, y1 );
} // End else
} // End if
else if (Flags&MESH_SOLID) // Solid Color
{
DrawPoints[0].x = x1;
DrawPoints[0].y = y1;
DrawPoints[1].x = x2;
DrawPoints[1].y = y2;
DrawPoints[2].x = x3;
DrawPoints[2].y = y3;
if (Flags&MESH_FLAT)
{
if (ShadeTable==NULL)
Color = Mesh->Surface;
else
{
Table = ShadeTable->GetTable();
Intensity = World->GetMeshIntensity ( Object, Mesh );
Color = Table[(Intensity&0xFF00)+Mesh->Surface];
} // End else
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
if (NumPts==4)
{
DrawPoints[1].x = x3;
DrawPoints[1].y = y3;
DrawPoints[2].x = x4;
DrawPoints[2].y = y4;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End if
} // End if
else if (Flags&MESH_GOURAUD)
{
DrawPoints[0].Intensity = Clipped[0].Intensity;
DrawPoints[1].Intensity = Clipped[1].Intensity;
DrawPoints[2].Intensity = Clipped[2].Intensity;
Color = Mesh->Surface;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
if (NumPts==4)
{
DrawPoints[1].x = x3;
DrawPoints[1].y = y3;
DrawPoints[2].x = x4;
DrawPoints[2].y = y4;
DrawPoints[1].Intensity = Clipped[2].Intensity;
DrawPoints[2].Intensity = Clipped[3].Intensity;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End if
} // End if
else
{
Color = Mesh->Surface;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
if (NumPts==4)
{
DrawPoints[1].x = x3;
DrawPoints[1].y = y3;
DrawPoints[2].x = x4;
DrawPoints[2].y = y4;
DrawPoints[1].Intensity = Clipped[2].Intensity;
DrawPoints[2].Intensity = Clipped[3].Intensity;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End if
} // End else
} // End else if
else if (Flags&MESH_TEXTURE) // Texture
{
if (TextureList==NULL)
return;
Texture = TextureList[Mesh->Texture];
DrawPoints[0].x = x1;
DrawPoints[0].y = y1;
DrawPoints[1].x = x2;
DrawPoints[1].y = y2;
DrawPoints[2].x = x3;
DrawPoints[2].y = y3;
DrawPoints[0].u = Clipped[0].u;
DrawPoints[0].v = Clipped[0].v;
DrawPoints[1].u = Clipped[1].u;
DrawPoints[1].v = Clipped[1].v;
DrawPoints[2].u = Clipped[2].u;
DrawPoints[2].v = Clipped[2].v;
if (Flags&MESH_FLAT)
{
Intensity = World->GetMeshIntensity ( Object, Mesh );
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
if (NumPts==4)
{
DrawPoints[1].x = x3;
DrawPoints[1].y = y3;
DrawPoints[2].x = x4;
DrawPoints[2].y = y4;
DrawPoints[1].u = Clipped[3].u;
DrawPoints[1].v = Clipped[3].v;
DrawPoints[2].u = Clipped[4].u;
DrawPoints[2].v = Clipped[4].v;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End if
} // End if
else if (Flags&MESH_GOURAUD)
{
DrawPoints[0].Intensity = Clipped[0].Intensity;
DrawPoints[1].Intensity = Clipped[1].Intensity;
DrawPoints[2].Intensity = Clipped[2].Intensity;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
if (NumPts==4)
{
DrawPoints[1].x = x3;
DrawPoints[1].y = y3;
DrawPoints[2].x = x4;
DrawPoints[2].y = y4;
DrawPoints[1].u = Clipped[3].u;
DrawPoints[1].v = Clipped[3].v;
DrawPoints[2].u = Clipped[4].u;
DrawPoints[2].v = Clipped[4].v;
DrawPoints[1].Intensity = Clipped[2].Intensity;
DrawPoints[2].Intensity = Clipped[3].Intensity;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End if
} // End if
else
{
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
if (NumPts==4)
{
DrawPoints[1].x = x3;
DrawPoints[1].y = y3;
DrawPoints[2].x = x4;
DrawPoints[2].y = y4;
DrawPoints[1].u = Clipped[3].u;
DrawPoints[1].v = Clipped[3].v;
DrawPoints[2].u = Clipped[4].u;
DrawPoints[2].v = Clipped[4].v;
DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
} // End if
} // End else
} // End else if
} // End else
} // End of DisplayMesh for G3DENGINE
VOID G3DENGINE::SetCamera ( double x, double y, double z,
double xa, double ya, double za )
{
Camera->SetPosition ( x, y, z );
Camera->SetAngle ( xa, ya, za );
} // End of SetCamera for G3DENGINE
VOID G3DENGINE::MoveCamera ( double x, double y, double z,
double xa, double ya, double za )
{
Camera->MovePosition ( x, y, z );
Camera->MoveAngle ( xa, ya, za );
} // End of MoveCamera for G3DENGINE
VOID G3DENGINE::MoveObject ( LONG Index, double x, double y, double z,
double xa, double ya, double za )
{
if (World==NULL)
return;
if ((Index<0)||(Index>=World->GetNumObjects()))
return;
G3DOBJECT **ObjectList;
ObjectList = World->GetObjectList ();
ObjectList[Index]->Move ( x, y, z, xa, ya, za );
} // End of MoveObject for G3DENGINE
INT CompareMesh ( const void *ptr1, const void *ptr2 )
{
G3DOBJECT *Object1,*Object2;
MESH3D *Mesh1,*Mesh2;
Object1 = ((MESHNODE*)ptr1)->Object;
Object2 = ((MESHNODE*)ptr2)->Object;
Mesh1 = ((MESHNODE*)ptr1)->Mesh;
Mesh2 = ((MESHNODE*)ptr2)->Mesh;
/*
if (Mesh1->MinZ>Mesh2->MaxZ)
return -1;
else if (Mesh1->MaxZ<Mesh2->MinZ)
return 1;
if (Mesh1->MinZ+Mesh1->MaxZ<Mesh2->MinZ+Mesh2->MaxZ)
return 1;
else if (Mesh2->MinZ<Mesh1->MinZ)
return -1;*/
if (Mesh1->MaxZ > Mesh2->MaxZ)
return -1;
else if (Mesh1->MaxZ < Mesh2->MaxZ)
return 1;
return 0;
} // End of CompareMesh
VOID G3DENGINE::SortMesh ()
{
qsort ( VisibleMeshes, NumVisibleMeshes, sizeof(MESHNODE), CompareMesh );
} // End of SortMesh for G3DENGINE
VOID G3DENGINE::AddVisibleMesh ( G3DOBJECT *Object, MESH3D *Mesh )
{
VisibleMeshes[NumVisibleMeshes].Object = Object;
VisibleMeshes[NumVisibleMeshes].Mesh = Mesh;
NumVisibleMeshes++;
} // End of AddVisibleMesh
VOID G3DENGINE::SetShadeTable ( SHADETABLE *Table )
{
ShadeTable = Table;
NumShadeLevels = ShadeTable->GetNumDarkLevels () + 1 +
ShadeTable->GetNumLightLevels ();
MaxShadeNumber = NumShadeLevels*256;
} // End of SetShadeTable for G3DENGINE
INT G3DENGINE::ReadToken ( FILEHANDLE f, STRING String )
{
return fscanf ( f, "%s", String );
} // End of ReadToken for G3DENGINE
INT G3DENGINE::GoToToken ( FILEHANDLE f, STRING String )
{
BOOLEAN Found=FALSE;
CHAR Str[128];
while (!Found)
{
if (ReadToken ( f, Str )==EOF)
return EOF;
if (strcmp(String,Str)==0)
Found = TRUE;
} // End while
return 0;
} // End of GoToToken for G3DENGINE
INT G3DENGINE::GetNumber ( FILEHANDLE f, double *Number )
{
CHAR Str[128];
INT Result;
Result = fscanf ( f, "%s", Str );
*Number = atof ( Str );
return Result;
} // End of GetNumber for G3DENGINE
INT G3DENGINE::GetInt ( FILEHANDLE f, LONG *Number )
{
return fscanf ( f, "%d", Number );
} // End of GetInt for G3DENGINE
BOOLEAN G3DENGINE::LoadASC ( STRING FileName,
LINKEDLIST<POINT3D> *ListPoint,
LINKEDLIST<MESH3D> *ListMesh )
{
FILEHANDLE f;
f = File.Open ( FileName, OPEN_READ | OPEN_BINARY );
if (f==NULL)
return FAILURE;
BOOLEAN Done;
Done = FALSE;
double x,y,z;
LONG NumVertex,NumFaces;
POINT3D Point;
MESH3D Mesh;
LONG P1,P2,P3;
LONG LastVertex=0;
while (!Done)
{
if (GoToToken( f,"Vertices:" )==EOF)
Done = TRUE;
else
{
GetInt ( f, &NumVertex );
GoToToken( f,"Faces:" );
GetInt ( f, &NumFaces );
GoToToken ( f,"Vertex" );
GoToToken ( f, "list:" );
LONG i;
for (i=0;i<(LONG)NumVertex;i++)
{
CHAR NumStr[128];
GoToToken( f,"Vertex" );
sprintf ( NumStr, "%d:", i );
GoToToken ( f, NumStr );
ReadToken ( f, NumStr );
if (strlen(NumStr)>2)
x = atof ( NumStr+2 );
else
GetNumber ( f, &x );
ReadToken ( f, NumStr );
if (strlen(NumStr)>2)
y = atof ( NumStr+2 );
else
GetNumber ( f, &y );
ReadToken ( f, NumStr );
if (strlen(NumStr)>2)
z = atof ( NumStr+2 );
else
GetNumber ( f, &z );
Point.x = x;
Point.y = y;
Point.z = z;
ListPoint->AddObject ( Point );
} // End for
GoToToken( f,"Face" );
GoToToken ( f, "list:" );
for (i=0;i<(LONG)NumFaces;i++)
{
GoToToken( f,"Face" );
CHAR Str[128];
sprintf ( Str, "%d:", i );
GoToToken ( f, Str );
ReadToken ( f, Str );
P1 = atoi ( Str+2 );
ReadToken ( f, Str );
P2 = atoi ( Str+2 );
ReadToken ( f, Str );
P3 = atoi ( Str+2 );
Mesh.Points[0] = (LONG)P1+LastVertex;
Mesh.Points[1] = (LONG)P2+LastVertex;
Mesh.Points[2] = (LONG)P3+LastVertex;
ListMesh->AddObject ( Mesh );
} // End for
} // End else
LastVertex = NumVertex;
Done = TRUE;
} // End while
File.Close ( f );
return SUCCESS;
} // End of LoadASC for G3DENGINE
VOID G3DENGINE::SetShadeMethod ( LONG Shade )
{
ShadeMethod = Shade;
} // End of SetShadeMethod for G3DENGINE
VOID G3DENGINE::SetSurfaceMethod ( LONG Surface )
{
SurfaceMethod = Surface;
} // End of SetSurfaceMethod for G3DENGINE
VOID G3DENGINE::ShowView ( IMAGE *Image )
{
if (World==NULL)
return;
Dest = Image;
UpdateWorld ();
LONG i,j;
LONG NumObjects,NumMeshes;
G3DOBJECT **ObjectList;
G3DLIGHT **LightList;
NumObjects = World->GetNumObjects ();
ObjectList = World->GetObjectList ();
NumVisibleMeshes = 0;
for (i=0;i<NumObjects;i++)
{
if (ObjectList[i]->MaxZ>MIN_Z_DISTANCE)
{
LightList = World->GetLightList ();
ObjectList[i]->Project ( Distance );
ObjectList[i]->ProcessMeshes ();
if (ShadeMethod>SHADE_FLAT)
ObjectList[i]->ComputePointIntensity ( LightList );
NumMeshes = ObjectList[i]->GetNumMeshes ();
MESH3D *MeshList = ObjectList[i]->GetMeshList ();
for (j=0;j<NumMeshes;j++)
{
if (MeshList[j].Flags&MESH_VISIBLE)
AddVisibleMesh ( ObjectList[i], &(MeshList[j]) );
} // End for
} // End if
} // End for
SortMesh ();
for (i=0;i<NumVisibleMeshes;i++)
DisplayMesh ( VisibleMeshes[i].Object, VisibleMeshes[i].Mesh );
} // End of ShowView for G3DENGINE